package com.haoran.dwz.common.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.haoran.dwz.common.http.HttpClientRequest;
import com.haoran.dwz.common.http.HttpClientResponse;

public class HttpClientUtil {
	private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

	private CloseableHttpClient httpClient;

	public static HttpClientResponse doGet(HttpClientRequest httpClientRequest){
		HttpClientUtil util = new HttpClientUtil();
		util.init();
		HttpGet httpGet = new HttpGet(httpClientRequest.getUrl());
		return util.sendRequest(httpGet, httpClientRequest);
	}
	
	public static HttpClientResponse doPost(HttpClientRequest httpClientRequest){
		HttpClientUtil util = new HttpClientUtil();
		util.init();
		HttpPost httpPost = new HttpPost(httpClientRequest.getUrl());
		logger.info(httpPost.toString());
		return util.sendRequest(httpPost, httpClientRequest);
	}
	
	public static HttpClientResponse doPut(HttpClientRequest httpClientRequest){
		HttpClientUtil util = new HttpClientUtil();
		util.init();
		HttpPut httpPut = new HttpPut(httpClientRequest.getUrl());
		return util.sendRequest(httpPut, httpClientRequest);
	}
	
	public static HttpClientResponse doDelete(HttpClientRequest httpClientRequest){
		HttpClientUtil util = new HttpClientUtil();
		util.init();
		HttpDelete httpDelete = new HttpDelete(httpClientRequest.getUrl());
		return util.sendRequest(httpDelete, httpClientRequest);
	}
	
	private void init() {
		httpClient = HttpClientBuilder.create().build();
		logger.info("Start http client connection.");
	}

	private HttpClientResponse sendRequest(HttpRequestBase httpRequestBase, HttpClientRequest httpClientRequest) {
		HttpClientResponse httpClientResponse = new HttpClientResponse();
		try {
			String charset = "ISO-8859-1";
			Map<String, String> httpClientRequestheaders = httpClientRequest.getHeaders();
			if(httpClientRequestheaders != null){
				for (Map.Entry<String, String> entry : httpClientRequestheaders.entrySet()) {
					String key = entry.getKey();
					String value = entry.getValue();
					httpRequestBase.setHeader(key, value);
					if(key.toLowerCase().equals("content-type") && value.split(";").length>=2){
						charset = value.split(";")[1].split("=")[1];
					}
				}
			}
			if (httpRequestBase instanceof HttpEntityEnclosingRequestBase) {
				((HttpEntityEnclosingRequestBase) httpRequestBase)
						.setEntity(new StringEntity(httpClientRequest.getBody(),charset));
			}
			CloseableHttpResponse response = httpClient.execute(httpRequestBase);
			int statusCode = response.getStatusLine().getStatusCode();
			httpClientResponse.setStatusCode(statusCode);
			Header[] headers = response.getAllHeaders();
			Map<String,String> httpClientResponseHeaders = new HashMap<String,String>();
			for (Header header : headers) {
				httpClientResponseHeaders.put(header.getName(), header.getValue());
			}
			httpClientResponse.setHeaders(httpClientResponseHeaders);
			HttpEntity entity = response.getEntity();
			String body = IOUtils.toString(entity.getContent(),Charset.defaultCharset());
			httpClientResponse.setBody(body);
			logger.info(body);
		} catch (UnsupportedEncodingException e) {
			logger.error("This encoding is not supported!");
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			logger.error("This Client Protocol is not supported!");
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("This io is not supported!");
			e.printStackTrace();
		} finally {
			this.close();
		}
		return httpClientResponse;
	}
	
	public String url(String uri, Map<String,String> params){
		StringBuilder sb = new StringBuilder();
		uri = StringUtils.trim(uri);
		uri = StringUtils.removeEnd(uri, "/");
		uri = StringUtils.removeEnd(uri, "?");
		sb.append(uri);
		if (params != null && !params.isEmpty()) {
			sb.append("?");
			Iterator<Entry<String, String>> iterator = params.entrySet()
					.iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, String> pair = iterator.next();
				try {
					String keyString = pair.getKey();
					String valueString = pair.getValue();
					sb.append(keyString);
					sb.append("=");
					sb.append(valueString);
					sb.append("&");
				} catch (Exception e) {
					logger.error(e.getMessage());
				}
			}
		}
		return StringUtils.removeEnd(sb.toString(), "&");
	}

	private void close() {
		try {
			httpClient.close();
			logger.info("Close http client successfully!");
		} catch (IOException e) {
			logger.error("Close http client connection failed!");
			e.printStackTrace();
		}
	}
}
